﻿using System.Linq;
using COC.Character;
using COC.Character.AI.Internal.FSM;
using COC.Debug;
using COC.Internal.Handler;
using COC.Tools.AI.Motion;
using UnityEngine;
using System.Collections;
namespace COC.Tools.AI.Motion
{
    public class AIBehave : BaseBehaviourSupport
    {


        public Transform target;
        float distance;
        float MAXVELOCITY = 30;
        float speed = 10;
        public Vector3 originPos;
        bool reverse = false;
        private Vector3 velocity;
        private Vector3 eulerVelocity;
        ISteeringDriver steering;
        AIBehaveAware neighborAI;
        public Vector3[] path;
        Steering_Main main;
        bool enableMotion;
        [HideInInspector]
        public FSMConnector connector;
        public FSMState currState = FSMState.FOLLOW_LEADER;
        int p;

        public int playerId;
        // Use this for initialization

        /// <summary>
        /// a handle is convenient to open/close perform a behave.
        /// </summary>
        public void open(bool isOpen)
        {
            if (isOpen)
            {
                enableMotion = isOpen;
                connector.Call(currState);
                // StartCoroutine(Movement());
            }
        }
        /// <summary>
        /// a handle is convenient to check whether open to motion a behave.
        /// </summary>
        public bool isOpen()
        {
            return enableMotion;
        }
        void Start()
        {
            UnityEngine.Debug.Log(FSMState.NONE + "," + FSMState.SEEK + "," + FSMState.WANDER);
            steering = ISteeringDriver.getInstance();
            initialBaseMoveData();
            originPos = this.transform.position;
            distance = Vector3.Distance(this.transform.position, target.position);
            velocity = new Vector3(0, this.transform.position.y, 0);
            eulerVelocity = new Vector3(0, Random.Range(0, 360), 0);


            //main = FindObjectOfType<Steering_Main>();
            #region DEBUG
            if (Camera.main.GetComponent<SceneResourceHandler>().debug)
            {
                GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                go.renderer.material.color = new Color(155, 0, 100, 90f);
                go.name = "child";
                go.transform.position = this.transform.position;
                go.transform.localScale = new Vector3(ISteeringDriver.MAX_QUEUE_RADIUS + 3f, .01f, ISteeringDriver.MAX_QUEUE_RADIUS + 3f);
                go.transform.parent = this.transform;
            }
            #endregion
            setLeader();
            //movement = Vector3.Normalize(target.position - this.transform.position);
            //steering = Vector3.Normalize(target.position - this.transform.position) * (target.position - this.transform.position).magnitude;


            // StartCoroutine(Movement());
        }


        public void mFixedUpdate()
        {

            p++;
            DebugTool.Log("ffffff");


        }
        /* void OnDrawGizmos()
         {
             if (main.showAIRadius)
             {
                 Gizmos.color=Color.Lerp(Color.blue,Color.magenta,30);
                 Gizmos.DrawWireSphere(this.transform.position, ISteeringDriver.MAX_QUEUE_RADIUS);
             }   
         }*/


        private void setLeader()
        {
            leader = steering.getAllAvailableAI()[0];
            if (leader.go != null)
            {
                leader.isLeader = true;
                leader.go.name = leader.go.name + "_Leader";
                DebugTool.Log("leader:" + leader);
            }
            #region DEBUG
            if (Camera.main.GetComponent<SceneResourceHandler>().debug)
            {
                leader.go.transform.GetChild(0).renderer.material.color = Color.Lerp(Color.cyan, Color.gray, 0.9f);
            }
            #endregion
        }
        private void initialBaseMoveData()
        {
            this.iMove = new AIBehaveAware();
            this.iMove.id = steering.bindAgent<AIBehaveAware>(iMove);
            this.iMove.playerId = playerId;
            this.iMove.loopPath = true;
           
            this.iMove.go = this.gameObject;
            this.gameObject.name = this.gameObject.name + "_" + this.iMove.id;
            this.iMove.max_velocity = (float)(steering.MAX_VELOCITY * (0.8 + Random.Range(1.0f, 9.0f) * 0.2));
            this.iMove.rotation = this.transform.rotation;
            this.iMove.wireFSMConnector(this, null, typeof(FSMState));



            /* while (true)
             {
                if(Vector3.Distance((neighborAI.agentPos-this.transform.position).normalized,new Vector3(1,1,1)*1)<1)
                   break;
             }*/
        }

        private void disposeMoveBehavior()
        {
            steering.unbindAgent(this.iMove);
            this.iMove.id = 0;
        }

        AIBehaveAware leader;
        Vector3 zombiePos;



        #region invoke steering behaviour

        #region standby
        IEnumerator STANDBY_Enter()
        {
            while (true)
            {
                if (steering != null)
                    velocity = steering.followLeader(this.iMove, leader);
                yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
            }
        }
        #endregion
        #region join a queue
        IEnumerator QUEUE_Enter()
        {
            yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
        }
        #endregion
        IEnumerator invokePursueTarget()
        {
            yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
        }
        #region follow a leader
        IEnumerator FOLLOW_LEADER_Enter()
        {
            while (enableMotion)
            {
                if (leader.go != null)
                {

                    /* {

                         this.transform.position += steering;
       
                     if (Mathf.Abs(this.transform.position.x - originPos.x) > Mathf.Abs(target.position.x - originPos.x))
                         steering.x = -steering.x;
                     else steering.x = steering.x;
                     if (Mathf.Abs(this.transform.position.z - originPos.z) > Mathf.Abs(target.position.z - originPos.z))
                         steering.z = -steering.z;
                     else
                     {
                         steering.z = steering.z;
                     }
                    // movement = Vector3.Normalize(target.position - this.transform.position);
                     steering = Vector3.Normalize(target.position - this.transform.position) * MAXVELOCITY;
                     Debug.DrawLine(this.transform.position, steering, Color.green);*/
                    this.iMove.agentPos = this.transform.position;
                    this.iMove.targetPos = target.position;
                    this.iMove.velocity = velocity;
                    this.iMove.centerVect3 = steering.adjustVector3(iMove);
                    // if(!this.iMove.isLeader)
                    //eulerVelocity = steering.wander(this.iMove);
                    this.transform.eulerAngles = eulerVelocity;
                    //CASE ONE
                    if (Vector3.Distance(target.position, this.transform.position) > 1)
                    {
                        this.iMove.velocity = velocity;
                        velocity = Vector3.zero;
                        velocity = steering.followLeader(this.iMove, leader);
                        // 
                        //velocity = steering.followingPath(this.iMove, path);
                    }
                    if (Vector3.Distance(target.position, this.transform.position) < 1)
                    {
                        connector.Call(FSMState.FLEE);
                        yield break;
                    }
                    //CASE THREE
                    if (Vector3.Distance(target.position, this.transform.position) > 0 && Vector3.Distance(target.position, this.transform.position) < 1)
                    {
                        velocity = Vector3.zero;
                        // this.transform.position = target.position;
                    }
                    //CASE FOUR
                    zombiePos = Camera.main.WorldToViewportPoint(transform.position);
                    if (Mathf.Abs(zombiePos.x) > Screen.width)
                    {
                        this.transform.position -= Vector3.left * 5;
                    }
                    if (Mathf.Abs(zombiePos.y) > Screen.width)
                    {
                        this.transform.position -= Vector3.up * 5;
                    }
                    /*if(path!=null&&path.Length>0)
                        velocity = steering.pursuit(this.iMove, neighborAI);*/
                    // velocity = steering.pursuit(this.iMove,neighborAI);
                    velocity.y = 0;
                    // Debug.Log("case one:" + velocity);
                    //this.transform.TransformDirection(Vector3.forward);
                    this.transform.position += velocity;
                    yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
                }
                yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
            }
        }
        #endregion

        #region flee from position or ai

        IEnumerator FLEE_Enter()
        {
            while (enableMotion)
            {
                if(neighborAI==null)
                    neighborAI = steering.pickupNeighborAI();
                this.iMove.agentPos = this.transform.position;
                this.iMove.targetPos = target.position;
                this.iMove.velocity = velocity;
                this.iMove.centerVect3 = steering.adjustVector3(iMove);
                velocity = Vector3.zero;
                velocity = steering.evade(this.iMove, neighborAI);
                renderer.material.color = Color.red;
                DebugTool.Log("case two: neighborAI:" + neighborAI.velocity);
                this.transform.position += velocity;
                yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
            }
        }
        #endregion



        #region wandering between one place and another
        IEnumerator WANDER_Enter()
        {
            yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
        }
        #endregion

        #region die
        IEnumerator DIED_Enter()
        {
            yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
        }
        #endregion
        #region separation
        IEnumerator SEPARATION_Enter()
        {
            yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
        }
        #endregion
        IEnumerator COHESION_Enter()
        {
            yield return new WaitForSeconds(Random.Range(1, 9) / 10.0f);
        }
        #endregion

    }

}